package com.docmgmt.mvp.service;

import com.docmgmt.mvp.exception.BusinessException;
import io.minio.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 文件存储服务（MinIO）
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileStorageService {

    private final MinioClient minioClient;

    @Value("${minio.bucket-name:documents}")
    private String bucketName;

    /**
     * 上传文件到 MinIO
     *
     * @param file 上传的文件
     * @return 文件在 MinIO 中的存储路径
     */
    public String uploadFile(MultipartFile file) {
        try {
            // 确保 bucket 存在
            ensureBucketExists();

            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename != null && originalFilename.contains(".")
                    ? originalFilename.substring(originalFilename.lastIndexOf("."))
                    : "";

            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String uniqueFilename = timestamp + "/" + UUID.randomUUID() + extension;

            // 上传文件
            try (InputStream inputStream = file.getInputStream()) {
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(bucketName)
                                .object(uniqueFilename)
                                .stream(inputStream, file.getSize(), -1)
                                .contentType(file.getContentType())
                                .build()
                );
            }

            log.info("文件上传到 MinIO 成功: bucket={}, path={}", bucketName, uniqueFilename);
            return uniqueFilename;

        } catch (Exception e) {
            log.error("文件上传到 MinIO 失败", e);
            throw new BusinessException("文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从 MinIO 下载文件
     *
     * @param objectName 对象名称（存储路径）
     * @return 文件输入流
     */
    public InputStream downloadFile(String objectName) {
        try {
            return minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
        } catch (Exception e) {
            log.error("从 MinIO 下载文件失败: {}", objectName, e);
            throw new BusinessException("文件下载失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除 MinIO 中的文件
     *
     * @param objectName 对象名称（存储路径）
     */
    public void deleteFile(String objectName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            log.info("从 MinIO 删除文件成功: {}", objectName);
        } catch (Exception e) {
            log.error("从 MinIO 删除文件失败: {}", objectName, e);
            throw new BusinessException("文件删除失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成预签名URL（用于下载/预览）
     *
     * @param objectName    对象名称（存储路径）
     * @param expirySeconds 过期时间（秒）
     * @return 预签名URL
     */
    public String generatePresignedUrl(String objectName, int expirySeconds) {
        try {
            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .method(io.minio.http.Method.GET)
                            .expiry(expirySeconds)
                            .build()
            );
        } catch (Exception e) {
            log.error("生成预签名URL失败: {}", objectName, e);
            throw new BusinessException("生成下载链接失败: " + e.getMessage(), e);
        }
    }

    /**
     * 确保 bucket 存在，如果不存在则创建
     */
    private void ensureBucketExists() {
        try {
            boolean exists = minioClient.bucketExists(
                    BucketExistsArgs.builder().bucket(bucketName).build()
            );

            if (!exists) {
                minioClient.makeBucket(
                        MakeBucketArgs.builder().bucket(bucketName).build()
                );
                log.info("创建 MinIO bucket: {}", bucketName);
            }
        } catch (Exception e) {
            log.error("检查/创建 MinIO bucket 失败", e);
            throw new BusinessException("MinIO bucket 初始化失败: " + e.getMessage(), e);
        }
    }
}
